package ru.volgogradetzzz.math {
	import ru.volgogradetzzz.math.VMatrix3x3;
	import ru.volgogradetzzz.math.VVector3;
	
	/**
	 * ...
	 * @author volgogradetzzz
	 */
	public class VQuaternion {
		
		public var x:Number = 0;
		public var y:Number = 0;
		public var z:Number = 0;
		public var w:Number = 0;
		
		public function VQuaternion() {
			
		}
		
		public function multiplyCopyTo(q:VQuaternion, qCopyTo:VQuaternion):void {
			qCopyTo.x = w * q.x + x * q.w + y * q.z - z * q.y,
	        qCopyTo.y = w * q.y + y * q.w + z * q.x - x * q.z,
	        qCopyTo.z = w * q.z + z * q.w + x * q.y - y * q.x,
	        qCopyTo.w = w * q.w - x * q.x - y * q.y - z * q.z
		}
		
		public function normalize():void {
			var magnitude:Number = Math.sqrt(w * w + x * x + y * y + z * z);
			w /= magnitude;
			x /= magnitude;
			y /= magnitude;
			z /= magnitude;
		}
		
		public function fromAxis(axis:VVector3, ang:Number):void {
			ang *= 0.5;
			
			var sin:Number = Math.sin(ang);
			
			x = (axis.x * sin);
			y = (axis.y * sin);
			z = (axis.z * sin);
			w = Math.cos(ang);
		}
		
		public function fromEuler(h:Number, p:Number, b:Number):void {
			x = -Math.cos(h / 2) * Math.sin(p / 2) * Math.cos(b / 2) - Math.sin(h / 2) * Math.cos(p / 2) * Math.sin(b / 2);
			y = Math.cos(h / 2) * Math.sin(p / 2) * Math.sin(b / 2) - Math.sin(h / 2) * Math.cos(p / 2) * Math.cos(b / 2);
			z = Math.sin(h / 2) * Math.sin(p / 2) * Math.cos(b / 2) - Math.cos(h / 2) * Math.sin(p / 2) * Math.sin(b / 2);
			w = Math.cos(h / 2) * Math.cos(p / 2) * Math.cos(b / 2) + Math.sin(h / 2) * Math.sin(p / 2) * Math.sin(b / 2);
		}
		
		public function getMatrix(m:VMatrix3x3):void {
			m.m11 = 1 - 2 * y * y - 2 * z * z;
			m.m12 = 2 * x * y + 2 * w * z;
			m.m13 = 2 * x * z - 2 * w * y;
			m.m21 = 2 * x * y - 2 * w * z;
			m.m22 = 1 - 2 * x * x - 2 * z * z;
			m.m23 = 2 * y * z + 2 * w * x;
			m.m31 = 2 * x * z + 2 * w * y;
			m.m32 = 2 * y * z - 2 * w * x;
			m.m33 = 1 - 2 * x * x - 2 * y * y;
		}
		
		public function toString():String
		{
			return '( x = ' + x + ', y = ' + y + ', z = ' + z + ', w = ' + w + ' )';
		}
	}
}